export { }

// 1.1 生成指定范围随机数
const randomNum = (min: number, max: number): number => Math.floor(Math.random() * (max - min + 1)) + min;
// console.log(randomNum(1,2));

// 2.1 数组乱序
const arrScrambling = (arr: any): any => {
    for (let i = 0; i < arr.length; i++) {
        const randomIndex: number = Math.round(Math.random() * (arr.length - 1 - i)) + i;
        [arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];
    }
    return arr;
}

// 2.2 数组扁平化
const flatten = (arr: any): any => {
    let result: any = [];

    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            result = result.concat(flatten(arr[i]));
        } else {
            result.push(arr[i]);
        }
    }
    return result;
}

// 2.3 数组中获取随机数
const sample = (arr: any) => arr[Math.floor(Math.random() * arr.length)];


// 3.1 生成随机字符串
const randomString = (len: number): string => {
    let chars: string = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz123456789';
    let strLen: number = chars.length;
    let randomStr: string = '';
    for (let i = 0; i < len; i++) {
        randomStr += chars.charAt(Math.floor(Math.random() * strLen));
    }
    return randomStr;
};


// 3.2 字符串首字母大写
const fistLetterUpper = (str: string): string => {
    return str.charAt(0).toUpperCase() + str.slice(1);
};

// 3.3 手机号中间四位变成*
const telFormat = (tel: number | string): string => {
    tel = String(tel);
    return tel.substr(0, 3) + "****" + tel.substr(7);
};

// 3.4 驼峰命名转换成短横线命名
const getKebabCase = (str: string): string => {
    return str.replace(/[A-Z]/g, (item) => '-' + item.toLowerCase())
}

// 3.5 短横线命名转换成驼峰命名
const getCamelCase = (str: string): string => {
    return str.replace(/-([a-z])/g, (i, item) => item.toUpperCase())
}

// 4.1 数字转化为大写金额
const digitUppercase = (n: number) => {
    const fraction: string[] = ['角', '分'];
    const digit: string[] = [
        '零', '壹', '贰', '叁', '肆',
        '伍', '陆', '柒', '捌', '玖'
    ];
    const unit: string[][] = [
        ['元', '万', '亿'],
        ['', '拾', '佰', '仟']
    ];
    n = Math.abs(n);
    let s: string = '';
    for (let i = 0; i < fraction.length; i++) {
        s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');
    }
    s = s || '整';
    n = Math.floor(n);
    for (let i = 0; i < unit[0].length && n > 0; i++) {
        let p: string = '';
        for (let j = 0; j < unit[1].length && n > 0; j++) {
            p = digit[n % 10] + unit[1][j] + p;
            n = Math.floor(n / 10);
        }
        s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
    }
    return s.replace(/(零.)*零元/, '元')
        .replace(/(零.)+/g, '零')
        .replace(/^整$/, '零元整');
};


// 5.1 存储loalStorage
const loalStorageSet = (key: string, value: string): void => {
    if (!key) return;
    if (typeof value !== 'string') {
        value = JSON.stringify(value);
    }
    window.localStorage.setItem(key, value);
};

// 5.2 获取localStorage
const loalStorageGet = (key: string): string => {
    if (!key) return '';
    const i: string | null = window.localStorage.getItem(key)
    return i !== null ? i : '';
};

// 5.3 删除localStorage
const loalStorageRemove = (key: string): void => {
    if (!key) return;
    window.localStorage.removeItem(key);
};

// 设置cookie
const setCookie = (key: string, value: string, expire: number): void => {
    const d = new Date();
    d.setDate(d.getDate() + expire);
    document.cookie = `${key}=${value};expires=${d.toUTCString()}`;
};

// 读取cookie
const getCookie = (key: string): string | null => {
    const cookieStr = unescape(document.cookie);
    const arr = cookieStr.split('; ');
    let cookieValue: string | null = null;
    for (let i = 0; i < arr.length; i++) {
        const temp = arr[i].split('=');
        if (temp[0] === key) {
            cookieValue = temp[1];
            break;
        }
    }
    return cookieValue;
};

// 正则校验身份证号码
const checkCardNo = (value: string): boolean => {
    let reg: RegExp = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    return reg.test(value);
};

// 正则校验是否包含中文
const haveCNChars = (value: string): boolean => {
    return /[\u4e00-\u9fa5]/.test(value);
}

// 获取URL参数列表
const GetRequest = (): { [key: string]: any | any[] | boolean } => {
    const url = location.search;
    const paramsStr = /.+\?(.+)$/.exec(url)?.[1];
    const paramsArr = paramsStr?.split('&') ?? [];
    const paramsObj: { [key: string]: any | any[] | boolean } = {};
    paramsArr.forEach(param => {
        const [key, val] = param.split('=');
        const decodedVal = decodeURIComponent(val ?? '');
        const numericVal = /^\d+$/.test(decodedVal) ? parseFloat(decodedVal) : decodedVal;
        if (param.includes('=')) {
            if (!paramsObj.hasOwnProperty(key)) {
                paramsObj[key] = numericVal;
            } else if (Array.isArray(paramsObj[key])) {
                (paramsObj[key] as any[]).push(numericVal);
            } else {
                paramsObj[key] = [paramsObj[key], numericVal];
            }
        } else {
            paramsObj[key] = true;
        }
    });
    return paramsObj;
};

// 键值对拼接成URL参数
const joinUrlParams = (params: { [key: string]: any }): string => {
    return Object.keys(params)
        .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
        .join('&');
}

// 判断是移动还是PC设备
const isMobile = (): string => {
    if ((navigator.userAgent.match(/(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i))) {
        return 'mobile';
    }
    return 'desktop';
}

// 判断是Windows还是Mac系统
const isAppleMobileDevice = (): boolean => {
    let reg: RegExp = /iphone|ipod|ipad|Macintosh/i;
    return reg.test(navigator.userAgent.toLowerCase());
}

// 滚动到页面顶部
const scrollToTop = (): void => {
    const height: number = document.documentElement.scrollTop || document.body.scrollTop;
    if (height > 0) {
        window.requestAnimationFrame(scrollToTop);
        window.scrollTo(0, height - height / 8);
    }
}

// 获取可视窗口高度
const getClientHeight = (): number => {
    let clientHeight: number = 0;
    if (document.body.clientHeight && document.documentElement.clientHeight) {
        clientHeight = (document.body.clientHeight < document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
    }
    else {
        clientHeight = (document.body.clientHeight > document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
    }
    return clientHeight;
}

// 格式化时间
const dateFormater = (formater: string, time: string): string => {
    let date: Date = time ? new Date(time) : new Date(),
        Y = date.getFullYear() + '',
        M = date.getMonth() + 1,
        D = date.getDate(),
        H = date.getHours(),
        m = date.getMinutes(),
        s = date.getSeconds();
    return formater.replace(/YYYY|yyyy/g, Y)
        .replace(/YY|yy/g, Y.substr(2, 2))
        .replace(/MM/g, (M < 10 ? '0' : '') + M)
        .replace(/DD/g, (D < 10 ? '0' : '') + D)
        .replace(/HH|hh/g, (H < 10 ? '0' : '') + H)
        .replace(/mm/g, (m < 10 ? '0' : '') + m)
        .replace(/ss/g, (s < 10 ? '0' : '') + s)
}

// 防抖函数
const debounce = (func: Function, wait: number): Function => {
    let timeout: number | null = null;
    return function (this: unknown, ...args: any[]): void {
        if (timeout !== null) clearTimeout(timeout);
        timeout = setTimeout(() => {
            func.apply(this, args);
        }, wait);
    };
};

// 节流函数
const throttle = (func: Function, wait: number): Function => {
    let timeout: number | null = null;
    let called = false;
    return function (this: unknown, ...args: any[]): void {
        if (!called || !timeout) {
            if (timeout !== null) clearTimeout(timeout);
            timeout = setTimeout(() => {
                timeout = null;
                called = false;
            }, wait);
            func.apply(this, args);
            called = true;
        }
    };
};

// 对象深拷贝
const deepClone = (obj: any): any => {
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }
    if (obj instanceof Date) {
        return new Date(obj.getTime());
    }
    if (obj instanceof Array) {
        let arr: any[] = [];
        for (let i = 0; i < obj.length; i++) {
            arr[i] = deepClone(obj[i]);
        }
        return arr;
    }
    if (obj instanceof Object) {
        let o: any = {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                o[key] = deepClone(obj[key]);
            }
        }
    }
}